"""
  Models.py file for i18ntext
  This defines a special type of Text that can hold multiple languages.

  The two useful models defined are:
      InternationalText
  and
      InternationalChar

  InternationalText is used for large international fields
  InternationalChar is used for fields < 256 characters

  Basic interface:
      foo = InternationalText...
      foo.translations()
   >>> [ a list of translations ]
   
"""
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from django.db    import models
import datetime


def post_save(object, model):
    """
    This isn't really too useful.
    It's supposed to allow you to specify a text value very easily.
    Using foo.itext.text = 'default'
          foo.itext.save()
    """
    
    lang = settings.LANGUAGE_CODE
    if hasattr(object, 'text') and isinstance(object.text, basestring):
        model.create(language        = lang,
                     text            = object.text,
                     translated_text = object)
    return

def find_translation(translations, language, return_closest):
    """
    Given a queryset of translations and a language (code),
    tries to find the closest match.
    """
    _NOT_AVAILABLE = ('none', _('Not available in your language.'))

    if translations.count() == 0:
        return _NOT_AVAILABLE

    cur_queryset = translations.filter(language = language)
    subset_queryset = translations.filter(language = language[:2])
    
    if len(cur_queryset) == 1:
        return (language, str(cur_queryset[0]))

    if len(cur_queryset) > 1:
        return (language, str(cur_queryset[0]))

    if len(subset_queryset) > 0:
        return (language, str(subset_queryset[0]))

    if not return_closest:
        return _NOT_AVAILABLE

    # try using setting's language code now
    if language != settings.LANGUAGE_CODE:
        cur_queryset = translations.filter(language = settings.LANGUAGE_CODE)
        if len(cur_queryset) > 0:
            return (language, str(cur_queryset[0]))

    # lost all hope, just pick one
    return (language, str(translations[0]))


class InternationalText(models.Model):
    class Admin:
        pass
    language = models.CharField(_('Default Language'),
        choices = settings.LANGUAGES,
        help_text=_('The default language of this particular text.'),
        maxlength=256, core=True)

    def get_lang_time(self, lang_code):
        """
        Gets the datetime of the last modified for a language if it exists.
        """
        try:
            trans = self.texttranslation_set.all().get(language=lang_code)
        except:
            return None

        return trans.modified
        

    def translations(self):
        """
        Returns the list of translated things.
        """
        return self.texttranslation_set.all()

    def set_lang(self, lang_code, text):
        """
        Sets the text of a translation given the language code.
        """

        try:
            trans = self.texttranslation_set.all().get(language = lang_code)
        except:
            trans = TextTranslation(translated_text = self,
                                    language = lang_code)

        
        trans.text = text
        trans.save()



    def render_with_lang(self, language_code = None, return_closest = True):

        if language_code is None:
            from django.conf import settings
            language_code = settings.LANGUAGE_CODE

        
        translations = self.texttranslation_set.all()
        return find_translation(translations, language_code, return_closest)


    def render(self, *args, **kwargs):
        return self.render_with_lang(*args, **kwargs)[1]
        
    __str__ = render

    def save(self):
        """
        Save this object, if 'text' is supplied, use that instead.
        """
        models.Model.save(self)
        post_save(self, TextTranslation)

class TextTranslation(models.Model):

    translated_text = models.ForeignKey(InternationalText,
                                        edit_inline=models.STACKED,
                                        num_in_admin = 1)
    language = models.CharField(_('Language'),
        choices = settings.LANGUAGES,
        help_text=_('Language of this particular text.'),
        maxlength=256, core=True)

    text     = models.TextField(_('Text'), core=True, blank=True)
    modified = models.DateTimeField(default = datetime.datetime.now)
    disabled = models.BooleanField(_('Disabled'), core=True, default=False)

    class Meta:
        unique_together = (('translated_text','language'),)

    def save(self):
        if len(self.text.strip()) == 0:
            if self.id:
                return self.delete()
            else:
                return
        models.Model.save(self)

    def __str__(self):
        return self.text


class InternationalChar(models.Model):
    class Admin:
        pass

    language = models.CharField(_('Default Language'),
        choices = settings.LANGUAGES,
        help_text=_('The default language of this particular text.'),
        maxlength=256, core=True)

    def set_lang(self, lang_code, text):
        """
        Sets the text of a translation given the language code.
        """

        try:
            trans = self.chartranslation_set.all().get(language = lang_code)
        except:
            trans = CharTranslation(translated_text = self,
                                    language = lang_code)

        
        trans.text = text
        trans.save()

    def translations(self):
        """
        Returns the list of translated things.
        """
        return self.chartranslation_set.all()

    def get_lang_time(self, lang_code):
        """
        Gets the datetime of the last modified for a language if it exists.
        """
        try:
            trans = self.chartranslation_set.all().get(language=lang_code)
        except:
            return None

        return trans.modified

    def render_with_lang(self, language_code = None, return_closest = True):
        if language_code is None:
            from django.conf import settings
            language_code = settings.LANGUAGE_CODE

        
        
        translations = self.chartranslation_set.all()

        return find_translation(translations, language_code, return_closest)



    def render(self, *args, **kwargs):
        return str(self.render_with_lang(*args, **kwargs)[1])
        
    __str__ = render

    def save(self):
        """
        Save this object, if 'text' is supplied, use that instead.
        """
        models.Model.save(self)
        post_save(self, TextTranslation)

class CharTranslation(models.Model):
    
    translated_text = models.ForeignKey(InternationalChar,
                                        edit_inline=models.STACKED,
                                        num_in_admin = 1)
    language = models.CharField(_('Language'),
        choices = settings.LANGUAGES,
        help_text=_('Language of this particular text.'),
        maxlength=256, core=True)

    text     = models.CharField(_('Text'), core=True, blank=True, maxlength=256)
    modified = models.DateTimeField(default = datetime.datetime.now)
    disabled = models.BooleanField(_('Disabled'), core=True, default=False)

    class Meta:
        unique_together = (('translated_text','language'),)

    def save(self):
        if len(self.text.strip()) == 0:
            return self.delete()
        models.Model.save(self)

    def __str__(self):
        return self.text
